package com.hrbxlh.util;

import com.alibaba.dcm.DnsCacheManipulator;
import com.hrbxlh.exception.OpenstackException;
import org.apache.commons.lang3.StringUtils;
import org.openstack4j.api.Builders;
import org.openstack4j.api.OSClient;
import org.openstack4j.model.common.Identifier;
import org.openstack4j.model.common.Payload;
import org.openstack4j.model.common.Payloads;
import org.openstack4j.model.compute.Flavor;
import org.openstack4j.model.compute.Server;
import org.openstack4j.model.compute.VNCConsole;
import org.openstack4j.model.image.ContainerFormat;
import org.openstack4j.model.image.DiskFormat;
import org.openstack4j.model.image.Image;
import org.openstack4j.openstack.OSFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.DecimalFormat;
import java.util.List;
import java.util.Properties;

/**
 * -------------------------------------------------------
 * Copyright (c) 2017, 鑫联华信息科技股份有限公司
 * All rights reserved.
 * FileName：OpenstackUtil.java
 * Description：虚拟机管理util类,负责与openstack的交互
 * History：
 * Date           Author               Desc
 * 2017-5-7		 王晨                 建立
 * -------------------------------------------------------
 */

public final class OpenstackUtil {

    private OpenstackUtil(){}

    private static Logger logger = LoggerFactory.getLogger(OpenstackUtil.class);

    private static Properties props;

    private static String url;
    private static String domain;
    private static String project;
    private static String username;
    private static String password;

    //加载openstack配置文件
    static {
        String fileName = "openstack.properties";
        props = new Properties();
        try {
            props.load(new InputStreamReader(PropertiesUtil.class.getClassLoader().getResourceAsStream(fileName)));
            url = getProperty("url");
            domain = getProperty("domain");
            project = getProperty("project");
            username = getProperty("username");
            password = getProperty("password");
        } catch (IOException e) {
            logger.error("配置文件读取异常", e);
        }
    }

    //设置DNS
    static {
        DnsCacheManipulator.setDnsCachePolicy(-1);
        DnsCacheManipulator.setDnsCache("controller", url.split(":")[1].substring(2));
        System.out.println(url.split(":")[1].substring(2));
    }

    /**
     * @description 查询虚拟机列表
     * @return
     */
    public static List<? extends Server> queryVirtualMachine() throws OpenstackException {
        try {
            return identify().compute().servers().list();
        } catch (Exception e) {
            throw new OpenstackException(e);
        }
    }

    /**
     * @description 删除某个虚拟机
     * @param serverId
     * @return
     */
    public static boolean deleteVirtualMachine(String serverId) throws OpenstackException {
        try {
            return identify().compute().servers().delete(serverId).getCode() == 200;
        } catch (Exception e) {
            e.printStackTrace();
            throw new OpenstackException();
        }
    }

    /**
     * @description 查询虚拟机模板列表
     * @return
     */
    public static List<? extends Flavor> queryFlavor() throws OpenstackException {
        try {
            return identify().compute().flavors().list();
        } catch (Exception e) {
            e.printStackTrace();
            throw new OpenstackException();
        }
    }

    /**
     * @description 查询虚拟机控制台的url
     * @param serverId
     * @return
     */
    public static String queryConsole(String serverId) {
        try {
            return identify().compute().servers().getVNCConsole(serverId, VNCConsole.Type.NOVNC).getURL();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * @description 读取配置信息
     * @param key
     * @return
     */
    private static String getProperty(String key){
        String value = props.getProperty(key.trim());
        if(StringUtils.isBlank(value)){
            return null;
        }
        return value.trim();
    }

    /**
     * @description openstack权限认证
     * @return
     */
    private static OSClient.OSClientV3 identify(){
        return OSFactory.builderV3()
                .endpoint(url)
                .credentials(username, password, Identifier.byName(domain))
                .scopeToProject(Identifier.byName(project), Identifier.byName(domain))
                .authenticate();
    }

    /**
     * @description 查询镜像列表
     * @return
     */
    public static List<? extends Image> queryImages(){
        return identify().images().list();
    }

    /**
     * @description 创建镜像
     * @param url
     * @param imageName
     * @param format
     * @return
     * @throws Exception
     */
    public static String createImage(String url, String imageName, String format) throws Exception{
        try {
            Payload<File> payload = Payloads.create(new File(url));
            Image image = identify().images().create(Builders.image()
                    .name(imageName)
                    .isPublic(true)
                    .containerFormat(ContainerFormat.BARE)
                    .diskFormat(DiskFormat.value(format))
                    .build(), payload);
            return image.getId();
        } catch (Exception e) {
            throw e;
        }
    }

    /**
     * @description 字节数转化为KB、MB、GB
     * @param size
     * @return
     */
    public static String formatImageSize(long size) {

        DecimalFormat df = new DecimalFormat("#.0");
        String fileSizeString;
        if (size < 1024) {
            fileSizeString = df.format((double) size) + " B";
        } else if (size < 1048576) {
            fileSizeString = df.format((double) size / 1024) + " KB";
        } else if (size < 1073741824) {
            fileSizeString = df.format((double) size / 1048576) + " MB";
        } else {
            fileSizeString = df.format((double) size / 1073741824) + " GB";
        }
        return fileSizeString;
    }
}